#include "PlayerModel.h"
#include <QDebug>
#include <QStandardPaths>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QVariantMap>
#include <algorithm>

PlayerModel::PlayerModel(QObject *parent)
    : QObject(parent)
    , m_settings("LitterPutting", "PlayerProfile")
    , m_cloudSyncSettings(nullptr)
{
    // 使用独立的配置文件保存云同步配置
    QString configPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir().mkpath(configPath);
    QString cloudConfigFile = configPath + "/cloud_sync_config.ini";
    m_cloudSyncSettings = new QSettings(cloudConfigFile, QSettings::IniFormat, this);
    
    loadProfile();
    loadCloudSyncConfig();
}

void PlayerModel::setName(const QString& name)
{
    if (m_profile.name != name) {
        m_profile.name = name;
        emit nameChanged();
        saveProfile();
    }
}

void PlayerModel::setAvatar(const QString& avatar)
{
    if (m_profile.avatar != avatar) {
        m_profile.avatar = avatar;
        emit avatarChanged();
        saveProfile();
    }
}

void PlayerModel::setTotalPoints(int points)
{
    int clampedPoints = std::max(0, points);
    if (m_profile.totalPoints != clampedPoints) {
        m_profile.totalPoints = clampedPoints;
        emit totalPointsChanged();
        saveProfile();
    }
}

void PlayerModel::setTotalStars(int stars)
{
    int clampedStars = std::max(0, stars);
    if (m_profile.totalStars != clampedStars) {
        m_profile.totalStars = clampedStars;
        emit totalStarsChanged();
        saveProfile();
    }
}

void PlayerModel::saveProfile()
{
    m_settings.setValue("name", m_profile.name);
    m_settings.setValue("avatar", m_profile.avatar);
    m_settings.setValue("totalPoints", m_profile.totalPoints);
    m_settings.setValue("totalStars", m_profile.totalStars);
    
    QJsonArray medalArray;
    for (const QVariant& medalVar : m_medals) {
        const QVariantMap medalMap = medalVar.toMap();
        QJsonObject obj;
        obj["id"] = medalMap.value("id").toString();
        obj["treeId"] = medalMap.value("treeId").toString();
        obj["skillId"] = medalMap.value("skillId").toInt();
        obj["name"] = medalMap.value("name").toString();
        obj["icon"] = medalMap.value("icon").toString();
        medalArray.append(obj);
    }
    QJsonDocument medalDoc(medalArray);
    m_settings.setValue("medals", QString::fromUtf8(medalDoc.toJson(QJsonDocument::Compact)));
    
    m_settings.sync();
}

void PlayerModel::loadProfile()
{
    m_profile.name = m_settings.value("name", "").toString();
    m_profile.avatar = m_settings.value("avatar", "").toString();
    m_profile.totalPoints = 0;
    m_profile.totalStars = 0;
    m_medals.clear();
    m_medalIds.clear();
    
    const QString medalsJson = m_settings.value("medals", "").toString();
    if (!medalsJson.isEmpty()) {
        QJsonParseError parseError;
        QJsonDocument doc = QJsonDocument::fromJson(medalsJson.toUtf8(), &parseError);
        if (parseError.error == QJsonParseError::NoError && doc.isArray()) {
            const QJsonArray array = doc.array();
            for (const QJsonValue& value : array) {
                const QJsonObject obj = value.toObject();
                const QString treeId = obj.value("treeId").toString();
                const int skillId = obj.value("skillId").toInt();
                const QString key = makeMedalKey(treeId, skillId);
                if (treeId.isEmpty() || m_medalIds.contains(key)) {
                    continue;
                }
                QVariantMap medal;
                medal["id"] = key;
                medal["treeId"] = treeId;
                medal["skillId"] = skillId;
                medal["name"] = obj.value("name").toString();
                QString storedIcon = obj.value("icon").toString();
                if (storedIcon.isEmpty()) {
                    storedIcon = QStringLiteral("🏅");
                }
                medal["icon"] = storedIcon;
                m_medals.append(medal);
                m_medalIds.insert(key);
            }
        }
    }
    
    // 如果是第一次运行，初始化默认配置
    if (m_profile.name.isEmpty()) {
        initializeDefaultProfile();
    }
    
    // 通知UI更新
    emit nameChanged();
    emit avatarChanged();
    emit totalPointsChanged();
    emit totalStarsChanged();
    emit medalsChanged();
}

void PlayerModel::initializeDefaultProfile()
{
    m_profile.name = "小勇士";
    m_profile.avatar = "🦸";  // 默认超级英雄表情
    m_profile.totalPoints = 0;
    m_profile.totalStars = 0;
    m_medals.clear();
    m_medalIds.clear();
    
    saveProfile();
}

void PlayerModel::addPoints(int points)
{
    setTotalPoints(m_profile.totalPoints + points);
}

void PlayerModel::addStars(int stars)
{
    setTotalStars(m_profile.totalStars + stars);
}

bool PlayerModel::hasMedal(const QString& treeId, int skillId) const
{
    return m_medalIds.contains(makeMedalKey(treeId, skillId));
}

void PlayerModel::addMedal(const QString& treeId, int skillId, const QString& name, const QString& icon)
{
    const QString key = makeMedalKey(treeId, skillId);
    if (treeId.isEmpty() || m_medalIds.contains(key)) {
        return;
    }

    QString normalizedIcon = icon;
    if (!normalizedIcon.isEmpty()) {
        normalizedIcon = normalizedIcon.trimmed();
    }

    QVariantMap medal;
    medal["id"] = key;
    medal["treeId"] = treeId;
    medal["skillId"] = skillId;
    medal["name"] = name;
    medal["icon"] = normalizedIcon.isEmpty() ? QStringLiteral("🏅") : normalizedIcon;
    
    m_medals.append(medal);
    m_medalIds.insert(key);
    
    emit medalsChanged();
    saveProfile();
}

void PlayerModel::removeMedal(const QString& treeId, int skillId)
{
    const QString key = makeMedalKey(treeId, skillId);
    if (!m_medalIds.contains(key)) {
        return;
    }
    
    for (int i = 0; i < m_medals.size(); ++i) {
        const QVariantMap medal = m_medals.at(i).toMap();
        if (medal.value("id").toString() == key) {
            m_medals.removeAt(i);
            break;
        }
    }
    
    m_medalIds.remove(key);
    emit medalsChanged();
    saveProfile();
}

void PlayerModel::updateMedalInfo(const QString& treeId, int skillId, const QString& newName, const QString& icon)
{
    const QString key = makeMedalKey(treeId, skillId);
    if (!m_medalIds.contains(key)) {
        return;
    }
    
    for (int i = 0; i < m_medals.size(); ++i) {
        QVariantMap medal = m_medals.at(i).toMap();
        if (medal.value("id").toString() == key) {
            bool changed = false;
            if (!newName.isEmpty() && medal.value("name") != newName) {
                medal["name"] = newName;
                changed = true;
            }
            QString normalizedIcon = icon.trimmed();
            if (!normalizedIcon.isEmpty() && medal.value("icon") != normalizedIcon) {
                medal["icon"] = normalizedIcon;
                changed = true;
            }
            if (changed) {
                m_medals[i] = medal;
                emit medalsChanged();
                saveProfile();
            }
            break;
        }
    }
}
// ==================== 云同步配置管理 ====================

void PlayerModel::loadCloudSyncConfig()
{
    m_giteeOwner = m_cloudSyncSettings->value("gitee/owner", "").toString();
    m_giteeRepo = m_cloudSyncSettings->value("gitee/repo", "").toString();
    m_giteeToken = m_cloudSyncSettings->value("gitee/token", "").toString();
    
    emit giteeOwnerChanged();
    emit giteeRepoChanged();
    emit giteeTokenChanged();
    emit cloudSyncEnabledChanged();
}

void PlayerModel::saveCloudSyncConfig()
{
    m_cloudSyncSettings->setValue("gitee/owner", m_giteeOwner);
    m_cloudSyncSettings->setValue("gitee/repo", m_giteeRepo);
    m_cloudSyncSettings->setValue("gitee/token", m_giteeToken);
    m_cloudSyncSettings->sync();
    
    emit cloudSyncEnabledChanged();
}

void PlayerModel::setGiteeOwner(const QString& owner)
{
    if (m_giteeOwner != owner) {
        m_giteeOwner = owner;
        emit giteeOwnerChanged();
        saveCloudSyncConfig();
    }
}

void PlayerModel::setGiteeRepo(const QString& repo)
{
    QString repoName = repo.trimmed();
    
    // 如果用户输入了完整URL，自动提取仓库名
    if (repoName.startsWith("http://") || repoName.startsWith("https://")) {
        QStringList parts = repoName.split('/');
        if (parts.size() >= 2) {
            repoName = parts.last();
        }
    }
    
    if (m_giteeRepo != repoName) {
        m_giteeRepo = repoName;
        emit giteeRepoChanged();
        saveCloudSyncConfig();
    }
}

void PlayerModel::setGiteeToken(const QString& token)
{
    if (m_giteeToken != token) {
        m_giteeToken = token;
        emit giteeTokenChanged();
        saveCloudSyncConfig();
    }
}

bool PlayerModel::cloudSyncEnabled() const
{
    return !m_giteeOwner.isEmpty() && !m_giteeRepo.isEmpty() && !m_giteeToken.isEmpty();
}

// ==================== 头像资源管理 ====================

QString PlayerModel::findSourceDirectory() const
{
    QString appDir = QCoreApplication::applicationDirPath();
    
    // 尝试不同的相对路径来定位源码目录
    QStringList possiblePaths = {
        appDir + "/../..",           // 典型的build/Debug或build/Release结构
        appDir + "/..",              // 直接在build目录
        appDir,                      // 当前目录
        appDir + "/../../.."         // 更深的build目录
    };
    
    for (const QString &path : possiblePaths) {
        QDir dir(path);
        QString testPath = dir.absolutePath() + "/qml.qrc";
        if (QFile::exists(testPath)) {
            return dir.absolutePath();
        }
    }
    
    return QString();  // 未找到
}

QString PlayerModel::makeMedalKey(const QString& treeId, int skillId) const
{
    return treeId + "#" + QString::number(skillId);
}

bool PlayerModel::checkForNewAvatars()
{
    m_newAvatars.clear();
    
    // 获取源码目录
    QString sourceDir = findSourceDirectory();
    if (sourceDir.isEmpty()) {
        return false;
    }
    
    QString qrcPath = sourceDir + "/qml.qrc";
    
    QString customAvatarDir = sourceDir + "/images/avatars/custom";
    
    // 检查目录是否存在
    QDir dir(customAvatarDir);
    if (!dir.exists()) {
        return false;
    }
    
    // 获取所有png文件
    QStringList filters;
    filters << "*.png";
    QFileInfoList pngFiles = dir.entryInfoList(filters, QDir::Files);
    
    // 读取qml.qrc文件
    QFile qrcFile(qrcPath);
    if (!qrcFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return false;
    }
    
    QString qrcContent = QString::fromUtf8(qrcFile.readAll());
    qrcFile.close();
    
    // 检查每个png文件是否在qml.qrc中
    for (const QFileInfo &fileInfo : pngFiles) {
        QString fileName = fileInfo.fileName();
        QString resourcePath = "images/avatars/custom/" + fileName;
        
        if (!qrcContent.contains(resourcePath)) {
            m_newAvatars.append(fileName);
        }
    }
    
    return !m_newAvatars.isEmpty();
}

QStringList PlayerModel::getNewAvatarList()
{
    return m_newAvatars;
}

bool PlayerModel::updateAvatarResources()
{
    if (m_newAvatars.isEmpty()) {
        emit avatarUpdateFailed("没有新的头像需要更新");
        return false;
    }
    
    // 获取源码目录
    QString sourceDir = findSourceDirectory();
    if (sourceDir.isEmpty()) {
        emit avatarUpdateFailed("无法找到源码目录");
        return false;
    }
    
    QString qrcPath = sourceDir + "/qml.qrc";
    
    // 读取qml.qrc文件
    QFile qrcFile(qrcPath);
    if (!qrcFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        emit avatarUpdateFailed("无法打开qml.qrc文件");
        return false;
    }
    
    QString qrcContent = QString::fromUtf8(qrcFile.readAll());
    qrcFile.close();
    
    // 在</qresource>标签之前插入新的文件条目
    QString newEntries;
    for (const QString &fileName : m_newAvatars) {
        newEntries += "        <file>images/avatars/custom/" + fileName + "</file>\n";
    }
    
    // 查找插入位置（在</qresource>之前）
    int insertPos = qrcContent.lastIndexOf("</qresource>");
    if (insertPos == -1) {
        emit avatarUpdateFailed("qml.qrc文件格式错误");
        return false;
    }
    
    // 插入新条目
    qrcContent.insert(insertPos, newEntries);
    
    // 写回qml.qrc文件
    if (!qrcFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        emit avatarUpdateFailed("无法写入qml.qrc文件");
        return false;
    }
    
    QTextStream out(&qrcFile);
    out.setEncoding(QStringConverter::Utf8);
    out << qrcContent;
    qrcFile.close();
    
    // 更新PlayerProfilePanel.qml文件
    QString qmlPath = sourceDir + "/qml/PlayerProfilePanel.qml";
    QFile qmlFile(qmlPath);
    if (!qmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        emit avatarUpdateSuccess("qml.qrc已更新！请手动在PlayerProfilePanel.qml的model数组中添加新头像，然后重新构建项目。");
        return true;  // qrc已更新，算部分成功
    }
    
    QString qmlContent = QString::fromUtf8(qmlFile.readAll());
    qmlFile.close();
    
    // 查找model数组的位置（在"// 图片头像"注释之后）
    int modelPos = qmlContent.indexOf("// 图片头像");
    if (modelPos == -1) {
        emit avatarUpdateSuccess("qml.qrc已更新！请手动在PlayerProfilePanel.qml的model数组中添加新头像，然后重新构建项目。");
        return true;
    }
    
    // 查找第一个qrc:路径后的位置
    int firstQrcPos = qmlContent.indexOf("\"qrc:/images/avatars/custom/", modelPos);
    if (firstQrcPos == -1) {
        emit avatarUpdateSuccess("qml.qrc已更新！请手动在PlayerProfilePanel.qml的model数组中添加新头像，然后重新构建项目。");
        return true;
    }
    
    // 查找该行结束位置
    int lineEndPos = qmlContent.indexOf("\n", firstQrcPos);
    
    // 构建新头像条目
    QString newQmlEntries;
    for (const QString &fileName : m_newAvatars) {
        newQmlEntries += "                    \"qrc:/images/avatars/custom/" + fileName + "\",\n";
    }
    
    // 插入新条目
    qmlContent.insert(lineEndPos + 1, newQmlEntries);
    
    // 写回QML文件
    if (!qmlFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        emit avatarUpdateSuccess("qml.qrc已更新！但无法写入PlayerProfilePanel.qml，请手动添加新头像后重新构建项目。");
        return true;
    }
    
    QTextStream outQml(&qmlFile);
    outQml.setEncoding(QStringConverter::Utf8);
    outQml << qmlContent;
    qmlFile.close();
    
    // 保存数量后清空缓存
    int count = m_newAvatars.size();
    m_newAvatars.clear();
    
    emit avatarUpdateSuccess("成功添加 " + QString::number(count) + " 个新头像！请重新构建项目以使用新头像。");
    return true;
}

